/**
 * 
 */
package de.cbf.cam.dsa.model.entities.maneuvers;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import org.hibernate.annotations.CollectionOfElements;

import de.cbf.cam.dsa.model.entities.BattleChar;
import de.cbf.cam.dsa.model.entities.Environment;
import de.cbf.cam.dsa.model.entities.constants.ManeuverConstants;
import de.cbf.cam.dsa.model.persistence.Header;
import de.cbf.util.entities.IntString;

/**
 * @author Nebelritter
 *
 */
@Entity
public class OneManeuver extends Header implements Cloneable {
	/**
	 * @uml.property  name="maneuverName"
	 */
	private String maneuverName ="";
	/**
	 * @uml.property  name="maneuverDescription"
	 */
	private String maneuverDescription ="";
	/**
	 * @uml.property  name="maneuverType"
	 */
	private int maneuverType;
	/**
	 * @uml.property  name="attackModifier"
	 */
	private Integer attackModifier = 0;
	/**
	 * @uml.property  name="defenseModifier"
	 */
	private Integer defenseModifier = 0;
	/**
	 * @uml.property  name="maxAttackModifier"
	 */
	private Integer maxAttackModifier = 0;
	/**
	 * @uml.property  name="maxDefenseModifier"
	 */
	private Integer maxDefenseModifier = 0;
	/**
	 * @uml.property  name="tpModifier"
	 */
	private Integer tpModifier = 0;
	/**
	 * @uml.property  name="minModifier"
	 */
	private Integer minModifier =-1;
	/**
	 * @uml.property  name="modifier"
	 */
	private Integer modifier =-1;
	
	/**
	 * @uml.property  name="exclAtMan"
	 */
	private List<String> excludedATManeuver = new ArrayList<String>(); 
	/**
	 * @uml.property  name="exclDefMan"
	 * @uml.associationEnd  multiplicity="(0 -1)" elementType="java.lang.String"
	 */
	private List<String> excludedDefenderManeunver = new ArrayList<String>();
	
	
	/**
	 * @uml.property  name="resolver"
	 * @uml.associationEnd  inverse="accordingManeuver:de.cbf.cam.dsa.model.entities.maneuvers.ManeuverResolverBase"
	 */
	private ManeuverResolverBase resolver;
//========================
//		constructors
//========================	
	/**
	 * 
	 */
	public OneManeuver() {
	
	}
//========================
//	   public methods
//========================
	
	@Transient	
	public boolean isPossibleFromAlreadyChosenManeuvers(List<OneManeuver> alreadyChosenManeuvers) {
		for (OneManeuver maneuver : alreadyChosenManeuvers) {
			switch (maneuverType) {
				case ManeuverConstants.TYPE_AT:{
					if(excludedATManeuver.contains(maneuver.maneuverName)){
						//excluded in attack
						return false;
					}
				}
				case ManeuverConstants.TYPE_PA:{
					if(excludedDefenderManeunver.contains(maneuver.maneuverName)){
						//excluded in attack
						return false;
					}	
				}
			}
		}
		return true;
	}
	@Transient	
	public boolean isPossibleFromSituation(BattleChar attacker,BattleChar defender,Environment env) {
		List<IntString> result = resolver.isPossibleFromSituation(attacker,defender,env);
		if(result!= null){
			for(int i = 0; i < result.size(); i++ ){
				IntString reason = result.get(i);
				maneuverDescription += reason.getDescription()+"\n";
				minModifier += reason.getValue();
				if(modifier<minModifier){
					modifier = minModifier;
				}
			}			
			return true;
		}
		return false;
	}
	
	
//========================
//    standard methods
//========================
	@Override
	public OneManeuver clone(){
		OneManeuver result = new OneManeuver();
		result.maneuverName = maneuverName;
		result.maneuverType = maneuverType;		
		result.attackModifier = attackModifier;
		result.defenseModifier = defenseModifier;
		result.maxAttackModifier = maxAttackModifier;
		result.defenseModifier = defenseModifier;
		result.minModifier = minModifier;
		result.tpModifier = tpModifier;
		result.resolver = resolver.clone();
		return result;
	}

	@Override
	public String toString() {
		return maneuverName;
	}
//========================
// 	   private methods
//========================

//========================
// 	SHORT property access
//========================
	
	

//========================
//		getters
//========================
	@Override
	@Id
	public String getGuid() {
		return guid;
	}
	@Override
	protected void setGuid(String guid) {
		this.guid = guid;		
	}
	
	/**
	 * @return
	 * @uml.property  name="maneuverName"
	 */
	public String getManeuverName() {
		return maneuverName;
	}
	/**
	 * @return
	 * @uml.property  name="attackModifier"
	 */
	public Integer getAttackModifier() {
		return attackModifier;
	}

	/**
	 * @return
	 * @uml.property  name="defenseModifier"
	 */
	public Integer getDefenseModifier() {
		return defenseModifier;
	}

	/**
	 * @return
	 * @uml.property  name="maxAttackModifier"
	 */
	public Integer getMaxAttackModifier() {
		return maxAttackModifier;
	}

	/**
	 * @return
	 * @uml.property  name="maxDefenseModifier"
	 */
	public Integer getMaxDefenseModifier() {
		return maxDefenseModifier;
	}
	/**
	 * @return
	 * @uml.property  name="tpModifier"
	 */
	public Integer getTpModifier() {
		return tpModifier;
	}
	/**
	 * @return
	 * @uml.property  name="minModifier"
	 */
	public Integer getMinModifier() {
		return minModifier;
	}
	
	/**
	 * @return
	 * @uml.property  name="maneuverType"
	 */
	public int getManeuverType() {
		return maneuverType;
	}
	/**
	 * @param type
	 * @uml.property  name="maneuverType"
	 */
	public void setManeuverType(int type) {
		this.maneuverType = type;
	}
//========================
//		setters
//========================
	/**
	 * @param name
	 * @uml.property  name="maneuverName"
	 */
	public void setManeuverName(String name){
		this.maneuverName = name;
	}
	
	/**
	 * @param attackModifier
	 * @uml.property  name="attackModifier"
	 */
	public void setAttackModifier(Integer attackModifier) {
		this.attackModifier = attackModifier;
	}

	/**
	 * @param defenseModifier
	 * @uml.property  name="defenseModifier"
	 */
	public void setDefenseModifier(Integer defenseModifier) {
		this.defenseModifier = defenseModifier;
	}

	/**
	 * @param maxAttackModifier
	 * @uml.property  name="maxAttackModifier"
	 */
	public void setMaxAttackModifier(Integer maxAttackModifier) {
		this.maxAttackModifier = maxAttackModifier;
	}

	/**
	 * @param maxDefenseModifier
	 * @uml.property  name="maxDefenseModifier"
	 */
	public void setMaxDefenseModifier(Integer maxDefenseModifier) {
		this.maxDefenseModifier = maxDefenseModifier;
	}
	
	/**
	 * @param tpModifier
	 * @uml.property  name="tpModifier"
	 */
	public void setTpModifier(Integer tpModifier) {
		this.tpModifier = tpModifier;
	}
	
	/**
	 * @param minModifier
	 * @uml.property  name="minModifier"
	 */
	public void setMinModifier(Integer minModifier) {
		this.minModifier = minModifier;
	}
	@CollectionOfElements()
	public List<String> getExclAtMan() {
		return excludedATManeuver;
	}
	/**
	 * @param excludedATManeuver the exclAtMan to set
	 */
	public void setExclAtMan(List<String> excludedAttackerManouvers) {
		this.excludedATManeuver = excludedAttackerManouvers;
	}	
	@CollectionOfElements()
	public List<String> getExclDefMan() {
		return excludedDefenderManeunver;
	}
	/**
	 * @param excludedDefenderManeunver the exclDefMan to set
	 */
	public void setExclDefMan(List<String> excludedDefenderManouvers) {
		this.excludedDefenderManeunver = excludedDefenderManouvers;
	}
	
	/**
	 * @return
	 * @uml.property  name="resolver"
	 */
	@OneToOne(cascade=CascadeType.ALL)
	public ManeuverResolverBase getResolver() {
		return resolver;
	}

	/**
	 * @param resolver
	 * @uml.property  name="resolver"
	 */
	public void setResolver(ManeuverResolverBase resolver) {
		this.resolver = resolver;
		resolver.setAccordingManeuver(this);
	}

	/**
	 * @return
	 * @uml.property  name="modifier"
	 */
	public Integer getModifier() {
		return modifier;
	}
	/**
	 * @param modifier
	 * @uml.property  name="modifier"
	 */
	public void setModifier(Integer modifier) {
		this.modifier = modifier;		
	}

	/**
	 * @return
	 * @uml.property  name="maneuverDescription"
	 */
	public String getManeuverDescription() {
		return maneuverDescription;
	}

	/**
	 * @param maneuverDescription
	 * @uml.property  name="maneuverDescription"
	 */
	public void setManeuverDescription(String maneuverDescription) {
		this.maneuverDescription = maneuverDescription;
	}

	

	

	


//========================
//		listeners
//========================

}
